/**
  ******************************************************************************
  * @file    mb_host.c
  * @author  Derrick Wang
  * @brief   modebus主机实现代码
  ******************************************************************************
  * @note
  * 该文件无需修改
  ******************************************************************************
  */

#include "mb.h"
#include "mb_include.h"
#include "string.h"

struct
{
	uint8_t state;						//modbus host状态
	uint8_t txLen;     					//需要发送的帧长度
	uint8_t txCounter;					//已发送bytes计数
	uint8_t txBuf[MB_RTU_MAX_SIZE];	    //发送缓冲区
	uint8_t rxCounter;					//接收计数
	uint8_t rxBuf[MB_RTU_MAX_SIZE];	    //接收缓冲区
#if (MODBUS_MODE == MB_MASTER)
	uint8_t errTimes;  					//失败次数计数
	uint8_t rxTimeOut;					//接收时的超时计数
#endif
}mb_t;


//modbus初始化
void mb_init(uint32_t baud,uint8_t parity)
{
	mb_port_uartInit(baud,parity);
	mb_port_timerInit(baud);
}

#if (MODBUS_MODE == MB_MASTER)
uint8_t mb_getState()
{
	return mb_t.state;
}

//发送一帧命令
int8_t mb_send(uint8_t add,uint8_t cmd,uint8_t *data,uint8_t data_len)
{
	uint16_t crc;
	if(mb_t.state!=MB_STATE_IDLE)return -1; //busy state

	mb_t.txCounter=0;
	mb_t.rxCounter=0;	
	mb_t.txBuf[0]=add;
	mb_t.txBuf[1]=cmd;
	memcpy((mb_t.txBuf+2),data,data_len);
	mb_t.txLen=data_len+2; //data(n)+add(1)+cmd(1)
	crc=mb_crc16(mb_t.txBuf,mb_t.txLen);
	mb_t.txBuf[mb_t.txLen++]=(uint8_t)(crc&0xff);
	mb_t.txBuf[mb_t.txLen++]=(uint8_t)(crc>>8);
	
	mb_t.state=MB_STATE_TX;
	mb_port_uartEnable(1,0);  //enable tx,disable rx
	/*当打开TXE中断以后，立马就会触发一次，所以这里不用先发送一个byte*/
	//mb_port_putchar(mb_t.txBuf[mb_t.txCounter++]); //send first char,then enter tx isr
	return 0;
}
#endif

//接收正确,进行解析处理
void mb_exec(uint8_t *pframe,uint8_t len)
{
	uint8_t datalen=len-2;
	switch(pframe[1])//cmd
	{
		case 1:
			mb_func_rec01(pframe[0],(pframe+2),datalen);
			break;
		case 2:
			mb_func_
			rec02(pframe[0],(pframe+2),datalen);
			break;
		case 3:
			mb_func_rec03(pframe[0],(pframe+2),datalen);
			break;
		case 4:
			mb_func_rec04(pframe[0],(pframe+2),datalen);
			break;
		case 5:
			mb_func_rec05(pframe[0],(pframe+2),datalen);
			break;
		case 6:
			mb_func_rec06(pframe[0],(pframe+2),datalen);
			break;
		case 15:
			mb_func_rec15(pframe[0],(pframe+2),datalen);
			break;
		case 16:
			mb_func_rec16(pframe[0],(pframe+2),datalen);
			break;
	}
}

void mb_poll()
{
	switch(mb_t.state)
	{
		/*接收完一帧数据,开始进行校验*/
		case MB_STATE_RX_CHECK:  //接收完成，对一帧数据进行检查
			if((mb_t.rxCounter>=MB_RTU_MIN_SIZE)&&(mb_crc16(mb_t.rxBuf,mb_t.rxCounter)==0)) 	//接收的一帧数据正确
			{
				if((mb_t.txBuf[0]==mb_t.rxBuf[0])&&(mb_t.txBuf[1]==mb_t.rxBuf[1]))			//发送帧数据和接收到的帧数据地址和功能码一样
				{
					mb_t.state=mb_STATE_EXEC;
				}
#if (MODBUS_MODE == MB_MASTER)
				else mb_t.state=MB_STATE_REC_ERR;
#endif	
			}
#if (MODBUS_MODE == MB_MASTER)
			else mb_t.state=MB_STATE_REC_ERR;
#endif
			break;

		/*确定接收正确执行回调*/
		case mb_STATE_EXEC:      //主机发送接收完成，执行回调
			mb_exec(mb_t.rxBuf,mb_t.rxCounter);
			mb_t.state=MB_STATE_IDLE;
			break;
#if (MODBUS_MODE == MB_MASTER)
		/*接收一帧数据出错*/	
		case MB_STATE_REC_ERR:
			mb_t.errTimes++;			
			if(mb_t.errTimes>=MB_ERR_MAX_TIMES)  
			{
				mb_t.state=MB_STATE_TIMES_ERR;
			}
			else  //重新再启动一次传输
			{
				mb_t.txCounter=0;
				mb_t.rxCounter=0;
				mb_t.state=MB_STATE_TX;
				mb_port_uartEnable(1,0);  //enable tx,disable rx
			}
			break;
		/*超过最大错误传输次数*/
		case MB_STATE_TIMES_ERR:
			mb_func_timesErr(mb_t.txBuf[0],mb_t.txBuf[1]);
			mb_t.txCounter=0;
			mb_t.rxCounter=0;
			break;
#elif (MODBUS_MODE == MB_SLAVER)
		case MB_STATE_REC_ERR:
			mb_t.txCounter=0;
			mb_t.rxCounter=0;
			mb_port_timerDisable();		//关闭定时器
			break;
#endif
	}
}


void mb_timer3T5Isr()
{
	switch(mb_t.state)
	{
#if (MODBUS_MODE == MB_MASTER)
		/*发送完但没有接收到数据*/
		case MB_STATE_TX_END:
			mb_t.rxTimeOut++;
			if(mb_t.rxTimeOut>=MB_REC_TIMEOUT) //接收超时
			{
				mb_t.rxTimeOut=0;
				mb_t.state=MB_STATE_REC_ERR;
				mb_port_timerDisable();		//关闭定时器
				mb_port_uartEnable(0,0); 	//串口tx、rx都关闭
			}
			break;
#endif
		case MB_STATE_RX:     	//3.5T到,接收一帧完成			
			mb_t.state=MB_STATE_RX_CHECK;
			mb_port_timerDisable();		//关闭定时器
			mb_port_uartEnable(0,0); 	//串口tx、rx都关闭
			break;
	}
	
}
void mb_uartRxIsr()
{
	uint8_t ch;
	mb_port_getchar(&ch);
	switch(mb_t.state)
	{
		case MB_STATE_TX_END:
			mb_t.rxCounter=0;
			mb_t.rxBuf[mb_t.rxCounter++]=ch;
			mb_t.state=MB_STATE_RX;
			mb_port_timerEnable();
			break;
		case MB_STATE_RX:
			if(mb_t.rxCounter<MB_RTU_MAX_SIZE)
			{
				mb_t.rxBuf[mb_t.rxCounter++]=ch;
			}
			else
				mb_t.state=MB_STATE_REC_ERR;
			mb_port_timerEnable();
			break;
		default:
			mb_port_timerEnable();
			break;		
	}
}
void mb_uartTxIsr()
{
	switch (mb_t.state)
	{
		case MB_STATE_TX:
			if(mb_t.txCounter==mb_t.txLen) //全部发送完
			{
				mb_t.state=MB_STATE_TX_END;
				mb_port_uartEnable(0,1);  //disable tx,enable rx
#if (MODBUS_MODE == MB_MASTER)
				mb_t.rxTimeOut=0;		  //清除接收超时计数
#endif
				mb_port_timerEnable();    //open timer
			}
			else
			{
				mb_port_putchar(mb_t.txBuf[mb_t.txCounter++]);
			}
			break;
		case MB_STATE_TX_END:
			mb_port_uartEnable(0,1);  	  //disable tx,enable rx
			break;
	}	
}



